<?php
/**
 * $id: opi_thumbnail.php
 *
 * oscProductImage version 2.0
 * Simple PHP THUMB for OsCommerce catalog images. 
 *
 * Copyright 2011, Zaenal Muttaqin
 * http://blog.lokamaya.net - http://lokamaya.com
 *
 * Licensed under the MIT license:
 * http://creativecommons.org/licenses/MIT/
 *
 
 Simple PHP THUMB for OsCommerce catalog images. 
 
 NOTE:
 ---------------
 This file only include 'includes/configure.php' without 'includes/application_top.php' file 
 to avoid loading any other files and database queries, thus make it faster.
 
 Therefore we must define some configuration manually:
 - OPI_FS_IMAGES_OPI_PATH  = absolute path to OPI image upload directory ( see configuration OPI: Absolute Path -  OSC_PRODUCT_IMAGE_ABSOLUTE_PATH )
 - OPI_FS_IMAGES_OPI_THUMB = Absolute path to thubmnail dir  ( see configuration OPI: Thumbnail Directory  - OSC_PRODUCT_IMAGE_THUMBNAIL_DIRECTORY )
 - OPI_FS_IMAGES_WATERMARK = Absolute path to watermark image
 - OPI_IMAGES_WM_WMIN = minimum image width: to add watermark to image
 - OPI_IMAGES_WM_HMIN = minimum image height: to add watermark to image
 
 EXAMPLE:
 ---------------
 - DEFINED MODE: 
 
   1. definedMode "display": thumbs/def/display/ 
      echo tep_image(DIR_WS_IMAGES . 'thumbs/def/display/somefolder/anyimage.jpg', 'Alt Text'); 
      // get relative URL -> <img alt="Alt Text" src="images/thumbs/def/display/somefolder/anyimage.jpg" />
      echo '<img alt="Alt Text" src="' . tep_href_link(DIR_WS_IMAGES . 'thumbs/def/display/somefolder/anyimage.jpg') . '" />';  
      //get full URL -> <img alt="Alt Text" src="http://mydomain.com/images/thumbs/def/display/somefolder/anyimage.jpg" />
      echo tep_image(tep_href_link(DIR_WS_IMAGES . 'thumbs/def/display/somefolder/anyimage.jpg'), 'Alt Text'); 
      // get full URL -> <img alt="Alt Text" src="http://mydomain.com/images/thumbs/def/display/somefolder/anyimage.jpg" />
   
   2. definedMode "small": thumbs/def/small/ 
      echo tep_image(DIR_WS_IMAGES . 'thumbs/def/small/somefolder/anyimage.jpg', 'Alt Text', 80, 80);
 
   3. definedMode "large": thumbs/def/large/ 
      echo tep_image(DIR_WS_IMAGES . 'thumbs/def/large/somefolder/anyimage.jpg', 'Alt Text');
      
   You can add/edit $definedMode array below around line 120 

 - CUSTOME MODE
   By default enabled. To disable it, set OPI_ENABLE_CUSTOME_MODE to false (around line 98).
 
   1. Fixed Width: thumbs/width/000/ 
      echo tep_image(DIR_WS_IMAGES . 'thumbs/width/200/somefolder/anyimage.jpg', 'Alt Text');
 
   2. Fixed Height: thumbs/height/000/
      echo tep_image(DIR_WS_IMAGES . 'thumbs/height/200/somefolder/anyimage.jpg', 'Alt Text');
   
   3. Clip (resize and cliping): thumbs/clip/000-000/ 
      echo tep_image(DIR_WS_IMAGES . 'thumbs/clip/200-300/somefolder/anyimage.jpg', 'Alt Text', 200, 300);

   4. Crop (crop without resizing): thumbs/crop/000-000/ 
      echo tep_image(DIR_WS_IMAGES . 'thumbs/crop/200-300/somefolder/anyimage.jpg', 'Alt Text', 200, 300);
   
   5. Auto (resizing without croping and cliping): thumbs/auto/000-000/ 
      echo tep_image(DIR_WS_IMAGES . 'thumbs/auto/200-300/somefolder/anyimage.jpg', 'Alt Text', 200, 300);
  
 
 APACHE REWRITE:
 ---------------
 Example for definedMode:
 # RewriteRule ^images/thumbs/def/([a-z]{3,16})/((.*)\.(gif|jp?g|png))                            opi_thumbnail.php?def=$1&file=$2 [NC,L]
 
 Example for custom mode:
 # RewriteRule ^images/thumbs/(crop|auto|clip)/([1-9][0-9]{1,2})-([1-9][0-9]{1,2})/((.*)\.(gif|jp?g|png))     opi_thumbnail.php?mode=$1&width=$2&height=$3&file=$4 [NC,L]
 # RewriteRule ^images/thumbs/(width|height)/([1-9][0-9]{1,2})/((.*)\.(gif|jp?g|png))                         opi_thumbnail.php?mode=$1&$1=$2&file=$3 [NC,L]

 More advanced technique can be found at readme.html


 NO APACHE REWRITE:
 ---------------
 Just call opi_thumbnail.php directly with query like below (don't forget to remove/commented line 93 below):
 - http://yourdomain/opi_thumbnail.php?def=DEFINEDMODE&file=RELATIVEPATHTOFILE, or
 - http://yourdomain/opi_thumbnail.php?mode=(clip|auto|crop)&width=200&height=400&file=RELATIVEPATHTOFILE, or
 - http://yourdomain/opi_thumbnail.php?mode=width&width=200&file=RELATIVEPATHTOFILE, or
 - http://yourdomain/opi_thumbnail.php?mode=height&height=400&file=RELATIVEPATHTOFILE
   
**/
require_once('includes/configure.php');
error_reporting(0);

//NO APACHE REWRITE, remove/commented below line
if (basename($_SERVER['REQUEST_URI']) == basename(__FILE__)) imageScale404(); //preventing direct access to this file

//disable custom mode: crop,auto,clip,width and height request
define('OPI_ENABLE_CUSTOME_MODE', false); //if you disabled it, also edit .htaccess and remove rewriteRule that command customMode

define('OPI_ENABLE_ADVANCED_REWRITE', true);  //deprecated

define('DIR_FS_OPIFILE_HERE', dirname(__FILE__));                               // absolute path to this file
define('OPI_FS_CHMOD', 0755);  // some servers required 0775 or 0777
define('OPI_FS_IMAGES_OPI_PATH', DIR_FS_OPIFILE_HERE . str_replace('/', DIRECTORY_SEPARATOR, '/'.DIR_WS_IMAGES) );             // OSC_PRODUCT_IMAGE_ABSOLUTE_PATH
define('OPI_FS_IMAGES_OPI_THUMB', OPI_FS_IMAGES_OPI_PATH . str_replace('/', DIRECTORY_SEPARATOR, '_thumbnail_/'));      // OSC_PRODUCT_IMAGE_ABSOLUTE_PATH + OSC_PRODUCT_IMAGE_THUMBNAIL_DIRECTORY
define('OPI_FS_IMAGES_WATERMARK', OPI_FS_IMAGES_OPI_PATH . str_replace('/', DIRECTORY_SEPARATOR, '_hidden_/watermarked.png') );  // watermark file

define('OPI_IMAGES_MAXWIDTH', 1000); //set to 0 to disable
define('OPI_IMAGES_MAXHEIGHT', 1000);//set to 0 to disable
define('OPI_IMAGES_MINWIDTH', 50);   //set to 0 to disable
define('OPI_IMAGES_MINHEIGHT', 50);  //set to 0 to disable

/*Watermark Position (default CC)*/
define('OPI_IMAGES_WM_WMIN', 600);          //set to 0 to disable watermark
define('OPI_IMAGES_WM_HMIN', 600);          //set to 0 to disable watermark
define('OPI_IMAGES_WM_POSITION', 'CC');     //TL (top-left), TC (top-center), TR (top-right), CL (center-left), CC (center-center), CR (center-right), BL (bottom-left), BC (bottom-center), and BR (bottom-right)
define('OPI_IMAGES_WM_OPACITY', 20);        //min 1, max 99 (integer), set to 0 will disable watermark


/*definedMode*/
$definedMode = array();

//do not edit adminthumb and adminpreview -> for administration page
$definedMode['adminthumb']     = array('mode'=>'clip',  'width'=>80,  'height'=>80);
$definedMode['adminpreview']   = array('mode'=>'width', 'width'=>150, 'height'=>0);

//you can edit/add/remove definedMode's below
$definedMode['display']   = array('mode'=>'clip',  'width'=>300, 'height'=>450);
$definedMode['small']     = array('mode'=>'clip',  'width'=>60,  'height'=>80);
$definedMode['thumb']     = array('mode'=>'clip',  'width'=>150, 'height'=>220);
$definedMode['large']     = array('mode'=>'auto',  'width'=>600, 'height'=>800);
$definedMode['square']    = array('mode'=>'clip',  'width'=>220, 'height'=>220);
$definedMode['customwidth']     = array('mode'=>'width', 'width'=>150, 'height'=>0);   //width & height must be defined
$definedMode['customheight']    = array('mode'=>'height','width'=>0,   'height'=>150); //width & height must be defined


if (isset($_GET['def'])) {
    list($mode, $width, $height) = array_values($definedMode[$_GET['def']]);
    $imMode = array(
        'mode'  =>  $mode,
        'requestWidth' =>  $width,
        'requestHeight'=>  $height,
        'file'  =>  isset($_GET['file']) ? imageScaleParseURL($_GET['file']) : null,
        'named' =>  $_GET['def']
    );
} elseif (OPI_ENABLE_CUSTOME_MODE === true) {
    $imMode = array(
        'mode'  =>  (isset($_GET['mode']) && in_array($_GET['mode'], array('crop', 'clip', 'width', 'height', 'auto'))) ? strtolower($_GET['mode']) : null,
        'requestWidth' =>  (isset($_GET['width']) && is_numeric($_GET['width'])) ? intval($_GET['width']) : null,
        'requestHeight'=>  (isset($_GET['height']) && is_numeric($_GET['height'])) ? intval($_GET['height']) : null,
        'file'  =>  isset($_GET['file']) ? imageScaleParseURL($_GET['file']) : null,
        'named' =>  null
    );
} else {
    imageScale404();
}

$imMode = array_merge($imMode, array('width'=>$imMode['requestWidth'], 'height'=>$imMode['requestHeight'], 'ratio'=>1, 'originalWidth'=>null, 'originalHeight'=>null, 'type'=>null, 'thumb'=>null, 'resize'=>false));

//imageScale404(true); //debug request

if ($imMode['mode'] === null || $imMode['file'] === null) {
    imageScale404();
}

if ($imMode['mode'] == 'width')
    $imMode['height'] = 0;
elseif ($imMode['mode'] == 'height')
    $imMode['width'] = 0;

if (OPI_IMAGES_MAXHEIGHT && $imMode['height'] > OPI_IMAGES_MAXHEIGHT) 
    $imMode['height'] = OPI_IMAGES_MAXHEIGHT;
elseif (OPI_IMAGES_MINHEIGHT && $imMode['height'] < OPI_IMAGES_MINHEIGHT)
    $imMode['height'] = OPI_IMAGES_MINHEIGHT;

if (OPI_IMAGES_MAXWIDTH && $imMode['width'] > OPI_IMAGES_MAXWIDTH) 
    $imMode['width'] = OPI_IMAGES_MAXWIDTH;
elseif (OPI_IMAGES_MINWIDTH && $imMode['width'] < OPI_IMAGES_MINWIDTH) 
    $imMode['width'] = OPI_IMAGES_MINWIDTH;

$prepare = imageScalePrepare();
if ($prepare === null) {
    imageScale404();
} elseif ($prepare === false) {
    imageScaleCreate();
}
imageScaleLoad();


/*SOME FUNCTION*/
function imageScaleParseURL($file) {
    $_path = pathinfo($file);
    //var_dump($_path);
    if (!isset($_path['extension']) || empty($_path['extension'])) return null;
    if (empty($_path['filename'])) return null;
    if (!preg_match("@^(gif|png|jpg|jpeg)$@i", $_path['extension'])) return null;
    if (strpos($file, '..') !== false) return null;
    if (preg_match("@(.*)\.php\/@i",$_path['dirname'].'/'.$_path['filename'].'/')) return null; //suspicious url
    if (preg_match("@^\.\/(.*)@i", $file) || preg_match("@[\(\)\[\]\n\t\r\!\$<>\:\{\}\|]+@i", $file)) return null;
    return $file;
}

function imageScale404($debug=false) {
    global $imMode;
    header("Status: 404 Not Found");
    header("HTTP/1.0 404 Not Found");
    header("HTTP/1.1 404 Not Found");
    die("File not found!");
}

function imageScalePrepare() {
    global $imMode;
    $source = OPI_FS_IMAGES_OPI_PATH . str_replace('/', DIRECTORY_SEPARATOR, $imMode['file']);
    
    $ratio = 1;
    $ratioW = 1;
    $ratioH = 1;
    $extensionAllowed = array('gif', 'jpg', 'png');
    $originalImage = @getimagesize($source);
    
    if ($originalImage && isset($extensionAllowed[$originalImage[2]-1])) {
        list($width, $height, $type, $attr) = $originalImage;
        $imMode['originalWidth'] = $width;
        $imMode['originalHeight'] = $height;
        $imMode['type'] = $extensionAllowed[$type-1];
        if ($imMode['type'] == 'jpg') {
            if (stristr($source, '.jpeg')) $imMode['type'] = 'jpeg';
        }
    } else {
        return null;
    }
    
    
    if ($imMode['mode'] == 'clip') {
        if ($imMode['width'] > $width) $imMode['width'] = $width;
        if ($imMode['height'] > $height) $imMode['height'] = $height;
    }
    
    if ($imMode['width'] != 0) {
        $ratioW = $imMode['width'] / $width;
    } else $imMode['width'] = $width;
    if ($imMode['height'] != 0) {
        $ratioH = $imMode['height'] / $height;
    } else $imMode['height'] = $height;
    
    $ratio = max($ratioW, $ratioH);
    //if ($ratioM > 1) $ratio = max($ratioM, $ratio);
    if ($imMode['mode'] == 'width') {
        if ($ratioW < 1) $ratio = $ratioW;
    } elseif ($imMode['mode'] == 'height') {
        if ($ratioH < 1) $ratio = $ratioH;
    } elseif ($imMode['mode'] == 'auto') {
        $ratio = min($ratioW, $ratioH);
    }
    $imMode['ratio'] = $ratio;
    //if ($ratioM > 1) $imMode['resize'] = $ratioM;
    
    if ($imMode['mode'] == 'clip' && $ratio != 1) {
        $imMode['resize'] = true;
    } elseif ($imMode['mode'] != 'crop' && $imMode['mode'] != 'clip') {
        $imMode['width'] = round($width*$ratio);
        $imMode['height'] = round($height*$ratio);
    }
    
    if (!$imMode['named']) {
        if ($imMode['mode'] == 'width') {
            $imMode['named'] = $imMode['mode'] . '-' . $imMode['requestWidth'];
        } elseif ($imMode['mode'] == 'height') {
            $imMode['named'] = $imMode['mode'] . '-' . $imMode['requestHeight'];
        } else {
            $imMode['named'] = $imMode['mode'] . '-' . $imMode['requestWidth'] . '-' . $imMode['requestHeight'];
        }
    }

    $imMode['thumb'] = $imMode['named'] . DIRECTORY_SEPARATOR . preg_replace('@[\/\\\]+@', DIRECTORY_SEPARATOR, strtolower($imMode['file']));
    
    //check directory
    $dirs = explode(DIRECTORY_SEPARATOR, $imMode['thumb']);
    $subdir = '';
    for ($i=0; $i < sizeof($dirs)-1; $i++) {
        $subdir .= $dirs[$i] . DIRECTORY_SEPARATOR;
        if (!is_dir(OPI_FS_IMAGES_OPI_THUMB . $subdir)) {
            @mkdir(OPI_FS_IMAGES_OPI_THUMB . $subdir, OPI_FS_CHMOD);
        }
    }
    
    if (file_exists(OPI_FS_IMAGES_OPI_THUMB . $imMode['thumb'])) {
        return true;
    }
    clearstatcache();
    return false;
}

function imageScaleCreate() {
    global $imMode;
    if (!$imMode['originalWidth'] || !$imMode['originalHeight'] || !$imMode['type']) {
        return imageScale404();
    }
    
    $source = OPI_FS_IMAGES_OPI_PATH . str_replace('/', DIRECTORY_SEPARATOR, $imMode['file']);
    $target = OPI_FS_IMAGES_OPI_THUMB . $imMode['thumb'];
    
    $width = $imMode['originalWidth'];
    $height = $imMode['originalHeight'];
    
    $dst = ImageCreateTrueColor($imMode['width'], $imMode['height']);
    $bgc = imagecolorallocate($dst, 255, 255, 255);
    imagefilledrectangle($dst, 0, 0, $imMode['width'], $imMode['height'], $bgc);
    
    $im  = null;
    if ($imMode['type']=='jpg' || $imMode['type']=='jpeg') $im = imagecreatefromjpeg($source);
    elseif ($imMode['type'] =='gif') $im = imagecreatefromgif($source);
    elseif ($imMode['type']=='png') $im = imagecreatefrompng($source);
    
    if ($im) {
      if ($imMode['mode']=='clip') {
        $posx =  abs(round((($width)-($imMode['width']/$imMode['ratio'])))/2);
        $posy =  abs(round((($height)-($imMode['height']/$imMode['ratio'])))/2);
        imagecopyresampled($dst, $im, 0, 0, $posx, $posy, round($width*$imMode['ratio']), round($height*$imMode['ratio']), $width, $height);
      } elseif ($imMode['mode']=='crop' || $imMode['mode']=='clip') {
        $posx =  abs($width-$imMode['width'])/2;
        $posy =  abs($height-$imMode['height'])/2;
        imagecopyresampled ($dst, $im, 0, 0, $posx, $posy, $width, $height, $width, $height);
      } else {
        imagecopyresampled ($dst, $im, 0, 0, 0, 0, $imMode['width'], $imMode['height'], $width, $height);
      }
      imageScaleWatermark($dst);
    
      if ($imMode['type']=='jpg' || $imMode['type']=='jpeg') imagejpeg($dst, $target);
      elseif ($imMode['type'] =='gif') imagegif($dst, $target);
      elseif ($imMode['type']=='png') $im = imagepng($dst, $target);
      imagedestroy($im);
    }
    imagedestroy($dst);
}

function imageScaleWatermark(&$img) {
    global $imMode;
    $watermark = OPI_FS_IMAGES_WATERMARK;
    $opacity   = min(intval(OPI_IMAGES_WM_OPACITY), 100);
    if ($opacity < 1 || !OPI_IMAGES_WM_WMIN || !OPI_IMAGES_WM_HMIN || $imMode['width'] < OPI_IMAGES_WM_WMIN || $imMode['height'] < OPI_IMAGES_WM_HMIN) return;
    
    list($width, $height, $type, $attr) = @getimagesize($watermark);
    if (!$width || !$height || !$type || intval($type) > 3 || intval($type) < 1) return;
    
    list($posX, $posY) = imageScalePositionWatermark($width, $height);

    $wat   = null;
    if ($type == 1)     $wat = imagecreatefromgif($watermark);
    elseif ($type == 2) $wat = imagecreatefromjpeg($watermark);
    elseif ($type == 3) $wat = imagecreatefrompng($watermark);
    
    $mark  = ImageCreateTrueColor($imMode['width'], $imMode['height']);
    @imagealphablending($img, TRUE);
    @imagealphablending($mark, TRUE);
    $trans = imageColorAllocate($mark, 100, 100, 100);
    imagefilledrectangle($mark, 0, 0, $imMode['width'], $imMode['height'], $trans);
    imagecolortransparent($mark, $trans);
    imagecopyresampled($mark, $wat, $posX, $posY, 0, 0, $width, $height, $width, $height);
    
    imagecopymerge($img, $mark, 0, 0, 0, 0, $imMode['width'], $imMode['height'], $opacity);
    imagedestroy($wat);
    imagedestroy($mark);
}

function imageScalePositionWatermark($waterW, $waterH) {
    global $imMode;
    
    $minWidth  = min($waterW, $imMode['width']);
    $minHeight = min($waterH, $imMode['height']);
    
    $posX = 0; $posY = 0;

    $pos = str_split(OPI_IMAGES_WM_POSITION);
    
    if     ($pos[0] == 'T') $posY = 0;
    elseif ($pos[0] == 'B') $posY = $imMode['height'] - $waterH;
    else                    $posY = round(($imMode['height']/2) - ($waterH/2));
    
    if     ($pos[1] == 'L') $posX = 0;
    elseif ($pos[1] == 'R') $posX = $imMode['width'] - $waterW;
    else                    $posX = round(($imMode['width']/2) - ($waterW/2));
    
    return array($posX, $posY, $minWidth, $minHeight);
}
    
function imageScaleLoad() {
    global $imMode;
    $target = OPI_FS_IMAGES_OPI_THUMB . $imMode['thumb'];
    
    $film = @filemtime($filename);
    //if ($film) {
    if (($imMode['type']=='jpg' || $imMode['type']=='jpeg') && $im = @imagecreatefromjpeg($target)) {
        header ( 'Content-Type: image/jpeg' );
        //header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s", $film) . " GMT");
        header("Cache-Control: public");
        //header("Pragma: no-cache");
        //header('Date: '.date('r'));
        imagejpeg($im);
        imagedestroy($im);
    } elseif ($imMode['type']=='gif' && $im = @imagecreatefromgif($target)) {
        header ( 'Content-Type: image/gif' );
        //header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s", $film) . " GMT");
        header("Cache-Control: public");
        //header("Pragma: no-cache");
        //header('Date: '.date('r'));
        imagegif($im);
        imagedestroy($im);
    } elseif ($imMode['type']=='png' && $im = @imagecreatefrompng($target)) {
        header ( 'Content-Type: image/png' );
        //header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s", $film) . " GMT");
        header("Cache-Control: public");
        //header("Pragma: no-cache");
        //header('Date: '.date('r'));
        imagepng($im);
        imagedestroy($im);
    } else {
        imageScale404();
    }
}
?>
